home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Games / Xconq 7.1.0 / src / xconq-7.1.0 / x11 / xinit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-07  |  55.1 KB  |  2,014 lines  |  [TEXT/R*ch]

  1. /* Initialization for the X11 interface to Xconq.
  2.    Copyright (C) 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996
  3.    Stanley T. Shebs.
  4.  
  5. Xconq is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.  See the file COPYING.  */
  9.  
  10. #include "conq.h"
  11. #include "xconq.h"
  12. extern int smallest_image PARAMS ((ImageFamily *imf, int *wp, int *hp));
  13.  
  14. extern XrmOptionDescRec xoptions[];
  15. extern int xoptions_count;
  16.  
  17. #ifndef __STDC__
  18. void abort ();
  19. #endif
  20.  
  21. static void init_gcs PARAMS ((Side *side));
  22. static void init_fonts PARAMS ((Side *side));
  23. static void init_bitmaps PARAMS ((Side *side));
  24. static void init_cursors PARAMS ((Side *side));
  25.  
  26. static void init_unit_images PARAMS ((Side *side));
  27. static void init_terrain_images PARAMS ((Side *side));
  28. static void init_emblem_images PARAMS ((Side *side));
  29. static void init_emblem PARAMS ((Side *side, Side *side2));
  30. static void get_default_terrain_image PARAMS ((Side *side, ImageFamily *imf,
  31.                           int t));
  32. static void get_default_emblem PARAMS ((Side *side, ImageFamily *imf,
  33.                        Side *side2));
  34. static void describe_imf PARAMS ((Side *side, char *classname, char *typename,
  35.                  ImageFamily *imf));
  36.  
  37. static void x11_interp_fn PARAMS ((ImageFamily *imf));
  38. static void x11_load_fn PARAMS ((ImageFamily *imf));
  39.  
  40. typedef struct s_varw {
  41.   Widget dialog;
  42.   char *value;
  43.   char *mess;
  44. } Varw;
  45.  
  46. typedef struct s_assignw {
  47.   Widget sidew, pname, pid;
  48.   char *vname, *vid, *messname, *messid;
  49.   int vflag;
  50. } Assignw;
  51.  
  52. typedef struct s_gamepop {
  53.   Widget shell;
  54.   Widget form;
  55.   Widget name;
  56.   Widget basemodule;
  57.   Widget version;
  58.   Widget title;
  59.   Widget blurb;
  60.   Widget instructions;
  61.   Widget notes;
  62.   Widget ok;
  63.   Widget add;
  64.   Widget verify;
  65.   Widget cancel;
  66.   Varw *variants;
  67.   int numvariants;
  68.   Assignw *assign;
  69. } GamePop;
  70.  
  71. typedef struct s_gamew {
  72.   Widget form;
  73.   Widget name;
  74.   Widget title;
  75.   Widget blurb;
  76.   GamePop *pop;
  77. } Gamew;
  78.  
  79.  
  80. static void popup_game PARAMS ((int g, int flag));
  81. static void quit_dialog PARAMS ((Widget w, XtPointer client_data,
  82.                  XtPointer call_data));
  83. static void game_callback PARAMS ((Widget w, XtPointer client_data,
  84.                    XtPointer call_data));
  85. static void cancel_dialog PARAMS ((Widget w, XtPointer client_data,
  86.                    XtPointer call_data));
  87. static void ok_dialog PARAMS ((Widget w, XtPointer client_data,
  88.                    XtPointer call_data));
  89. static void go_dialog PARAMS ((Widget w, XtPointer client_data,
  90.                    XtPointer call_data));
  91. static void verify_dialog PARAMS ((Widget w, XtPointer client_data,
  92.                    XtPointer call_data));
  93. static void add_player_dialog PARAMS ((Widget w, XtPointer client_data,
  94.                        XtPointer call_data));
  95. static int valid_gamepop PARAMS ((void));
  96. static void splat_obj_in_textw PARAMS ((Widget w, Obj *obj));
  97. static Widget createTextWidget PARAMS ((char *name, Widget parent,
  98.                     Widget up, Obj *obj));
  99. static char *variant_default PARAMS ((Variant *var));
  100. static char *variant_name PARAMS ((Variant *var));
  101. static void horizontalDialog PARAMS ((Widget w));
  102. static void reverseVideoDialog PARAMS ((Widget w));
  103. static void implement_variant PARAMS ((char *value, Variant *var));
  104. static int valid_variant PARAMS ((char *value, Variant *var));
  105. static int type_player PARAMS ((char *value));
  106. static void init_assignw_player PARAMS ((Assignw *assignw, Player *player));
  107. static int can_open_display PARAMS ((char *dpyname));
  108. static int boolean_lisp PARAMS ((char *value));
  109.  
  110. static int loop, chosen_game;
  111.  
  112. static Widget gameShell;
  113.  
  114. static Gamew *games;
  115.  
  116. /* we could share this buffers with other modules */
  117. char buf1[BUFSIZE], buf2[BUFSIZE], buf3[BUFSIZE], errormess[BUFSIZE];
  118.  
  119. Obj *variants;
  120.  
  121. char *imflib = IMFLIB;
  122.  
  123. /* Display and window globals used in callbacks from generic imf
  124.    handling code. */
  125.  
  126. Display *tmp_display;
  127.  
  128. Window tmp_root_window;
  129.  
  130. /* How much space to leave for a unit image, if all images should get
  131.    the same amount (such as for a list of unit types). */
  132.  
  133. int min_w_for_unit_image = 16;
  134. int min_h_for_unit_image = 16;
  135.  
  136. /* various bitmap definitions. */
  137.  
  138. #include "bitmaps/lookglass.b"
  139. #include "bitmaps/lookmask.b"
  140. #include "bitmaps/movecurs.b"
  141. #include "bitmaps/movemask.b"
  142. #include "bitmaps/shootcurs.b"
  143. #include "bitmaps/shootmask.b"
  144. #include "bitmaps/buildcurs.b"
  145. #include "bitmaps/buildmask.b"
  146.  
  147. #include "bitmaps/boxcurs.b"
  148. #include "bitmaps/boxmask.b"
  149.  
  150. #include "bitmaps/bomb1.b"
  151. #include "bitmaps/bomb2.b"
  152. #include "bitmaps/bomb3.b"
  153. #include "bitmaps/bomb4.b"
  154.  
  155. #include "bitmaps/miss.b"
  156. #include "bitmaps/hit.b"
  157. #include "bitmaps/kill.b"
  158.  
  159. #include "bitmaps/hex8.b"
  160. #include "bitmaps/hex8b.b"
  161. #include "bitmaps/hex16.b"
  162. #include "bitmaps/hex16b.b"
  163. #include "bitmaps/hex32.b"
  164. #include "bitmaps/hex32b.b"
  165.  
  166. #include "bitmaps/closer.b"
  167. #include "bitmaps/farther.b"
  168.  
  169. #include "bitmaps/gray.b"
  170. #include "bitmaps/darkgray.b"
  171.  
  172. #ifdef DESIGNERS
  173. #include "bitmaps/hexcurs.b"
  174. #include "bitmaps/hexcursmask.b"
  175. #include "bitmaps/bordcurs.b"
  176. #include "bitmaps/conncurs.b"
  177. #include "bitmaps/addunits.b"
  178. #include "bitmaps/people.b"
  179. #include "bitmaps/feature.b"
  180. #include "bitmaps/featuremask.b"
  181. #endif /* DESIGNERS */
  182.  
  183. /* (add arrays of info about various drawing styles and allowable options) */
  184.  
  185. enum whattouse terrstyles[] = {
  186.     useblocks,
  187.     useblocks,
  188.     useblocks,
  189.     useblocks,
  190.     usepictures,
  191.     usepictures,
  192.     usepolygons,
  193.     usepolygons
  194. };
  195.  
  196. /* The set of X11 resources that Xconq knows about. */
  197.  
  198. static XtResource resources[] = {
  199.     { XtNforeground, XtCForeground, XtRPixel, sizeof (Pixel),
  200.       XtOffsetOf(UI, foreground), XtRString, XtDefaultForeground },
  201.     { XtNbackground, XtCBackground, XtRPixel, sizeof (Pixel),
  202.       XtOffsetOf(UI, background), XtRString, XtDefaultBackground },
  203.     { XtNgeometry, XtCGeometry, XtRString, sizeof (String),
  204.       XtOffsetOf(UI, geospec), XtRString, NULL },
  205. };
  206.  
  207. /* Do a precheck of the intended displays.  This happens just after
  208.    player spec reading so that any losing displays can be found before
  209.    game startup gets in too deep. */
  210.  
  211. void
  212. check_player_displays()
  213. {
  214.     int numfailures = 0;
  215.     char *dpyname;
  216.     Player *player;
  217.     Display *dpy;
  218.  
  219.     for_all_players(player) {
  220.     /* Try to open the display. */
  221.     dpyname = player->displayname;
  222.     if (dpyname != NULL) {
  223.         if (strcmp("_", dpyname) == 0)
  224.           dpyname = getenv("DISPLAY");
  225.         dpy = XOpenDisplay(dpyname);
  226.         if (dpy == NULL) {
  227.         fprintf(stderr, "Cannot open display \"%s\"!\n", dpyname);
  228.         ++numfailures;
  229.         } else {
  230.         XCloseDisplay(dpy);
  231.         }
  232.     }
  233.     }
  234.     if (numfailures > 0) {
  235.     init_error("can't open all the required displays");
  236.     exit(1);
  237.     }
  238. }
  239.  
  240. /* Set up the basic user interface for a side.  This is called from the
  241.    kernel while doing the final assignment of players to sides, and
  242.    does not cause any display activity. */
  243.  
  244. void
  245. init_ui(side)
  246. Side *side;
  247. {
  248.     if (side_wants_display(side)) {
  249.         side->ui = (UI *) xmalloc(sizeof(UI));
  250.     Dprintf("One UI is %d bytes.\n", sizeof(UI));
  251.     } else {
  252.     side->ui = NULL;
  253.     }
  254. }
  255.  
  256. /* Set up all sides' displays all at once. */
  257.  
  258. int numdisplays;
  259.  
  260. void
  261. init_all_displays()
  262. {
  263.     Side *side;
  264.  
  265.     numdisplays = 0;
  266.     for_all_sides(side) {
  267.     if (side_has_display(side)) {
  268.         init_display(side);
  269.         ++numdisplays;
  270.     }
  271.     }
  272.     if (numdisplays == 0) {
  273.     fprintf(stderr, "Must have at least one display to start.\n");
  274.     exit(0);
  275.     }
  276. }
  277.  
  278. /* Do a full redraw on each display. */
  279.  
  280. void
  281. init_redraws()
  282. {
  283.     Side *side;
  284.  
  285.     for_all_sides(side) {
  286.     if (side->ui != NULL) {
  287.         /* The moment of truth - up to now output has been suppressed. */
  288.         side->ui->active = TRUE;
  289.         draw_all_maps(side);
  290.     }
  291.     }
  292. }
  293.  
  294. /* Open display, create all the windows we'll need, do misc setup things,
  295.    and initialize some globals to out-of-range values for recognition later. */
  296.  
  297. int toplevel_display_used = FALSE;
  298.  
  299. void
  300. init_display(side)
  301. Side *side;
  302. {
  303.     int argc, p, u, t, s, depth;
  304.     char *dpyname, *str;
  305.     Display *dpy;
  306.  
  307.     dpyname = side->player->displayname;
  308.  
  309.     Dprintf("Will try to open %s display `%s'...\n",
  310.         side_desig(side), dpyname);
  311.  
  312.     /* Detect the placeholder for the default display. */
  313.     if (strcmp("_", dpyname) == 0)
  314.       dpyname = getenv("DISPLAY");
  315.  
  316.     /* See if we can use the already-opened display for this side;
  317.        if not, then open one. */
  318.     dpy = NULL;
  319.     if (!toplevel_display_used) {
  320.     str = XDisplayString(XtDisplay(thistoplevel));
  321.     if (!empty_string(str) && strcmp(str, dpyname) == 0) {
  322.         dpy = XtDisplay(thistoplevel);
  323.         side->ui->shell = thistoplevel;
  324.         toplevel_display_used = TRUE;
  325.     }
  326.     }
  327.     if (dpy == NULL) {
  328.     argc = 0;
  329.     dpy = XtOpenDisplay(thisapp, dpyname, PROGRAMNAME, PROGRAMCLASSNAME,
  330.                 xoptions, xoptions_count, &argc, NULL);
  331.     side->ui->shell = XtAppCreateShell(PROGRAMNAME, PROGRAMCLASSNAME,
  332.                       topLevelShellWidgetClass, dpy,
  333.                       tmpargs, 0);
  334.     }
  335.     side->ui->dpy = dpy;
  336.  
  337.     if (DebugG)
  338.       XSynchronize(side->ui->dpy, True);
  339.  
  340.     XtGetApplicationResources(side->ui->shell, side->ui,
  341.                   resources, XtNumber(resources), NULL, 0);
  342.  
  343.     side->ui->kill_atom = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
  344.     /* Cache some generally useful values. */
  345.     side->ui->screen = DefaultScreen(dpy);
  346.     side->ui->rootwin = DefaultRootWindow(dpy);
  347.  
  348.     /* Set up things shared by all the windows. */
  349.     side->ui->dflt_color_terr_images = TRUE;
  350.     side->ui->dflt_color_unit_images = TRUE;
  351.     side->ui->dflt_color_embl_images = TRUE;
  352.     side->ui->bonw = BLACKONWHITE;
  353.     depth = XDisplayCells(dpy, side->ui->screen);
  354.     DGprintf("%d different colors available ...\n", depth);
  355.     side->ui->monochrome = (depth <= 2);
  356.     for (p = 0; p < NUMPOWERS; ++p) {
  357.     for_all_terrain_types(t) {
  358.         /* Decide what display technique to use at each power. */
  359.         side->ui->usewhat[p][t] = terrstyles[p];
  360.         side->ui->terrpics[p][t] = None;
  361.         side->ui->terrchars[p][t] = '\0';
  362.         side->ui->terrfonts[p][t] = NULL;
  363.     }
  364.     for_all_unit_types(u) {
  365.         side->ui->unitpics[p][u] = None;
  366.         side->ui->unitmasks[p][u] = None;
  367.         side->ui->unitchars[p][u] = '\0';
  368.         side->ui->unitfonts[p][u] = NULL;
  369.         side->ui->ulegendfonts[p][u] = NULL;
  370.         /* (these values really should be filled in better) */
  371.         side->ui->unitw[p][u] = 1;  side->ui->unith[p][u] = 1;
  372.     }
  373.     }
  374.     for (s = 0; s < MAXSIDES; ++s) {
  375.     side->ui->emblempics[s] = None;
  376.     side->ui->emblemmasks[s] = None;
  377.     }
  378.     set_colors(side);
  379.     init_fonts(side);
  380.     init_unit_images(side);
  381.     init_terrain_images(side);
  382.     init_emblem_images(side);
  383.     init_bitmaps(side);
  384.     init_gcs(side);
  385.     init_cursors(side);
  386.     /* Create the generic windows. */
  387.     side->ui->maps = NULL;
  388.  
  389.     create_map(side, 5, side->ui->geospec);
  390.  
  391.     /* At this point, the toplevel widget has been realized, so we can */
  392.     /* start doing things to it...  So, first things first: */
  393.     XSetWMProtocols(dpy, XtWindow(side->ui->shell),
  394.             &side->ui->kill_atom, 1);
  395.     XtOverrideTranslations(side->ui->shell,
  396.     XtParseTranslationTable("<Message>WM_PROTOCOLS: wm-quit()"));
  397.  
  398. #ifdef DESIGNERS
  399.     /* If this side is already a designer (perhaps via command-line option)
  400.        popup the design controls now. */
  401.     if (side->designer)
  402.       popup_design(side);
  403. #endif /* DESIGNERS */
  404.  
  405.     /* Preallocate space needed to save display state. */
  406.     ui_save_state(side);
  407.  
  408.     Dprintf("Successfully initialized `%s'!\n", dpyname);
  409. }
  410.  
  411. /* This will set up the correct set of colors at any point in the game.
  412.    Colors are all specified by name; if any are not available, it is up to
  413.    the graphics interface to supply a substitute. */
  414.  
  415. void
  416. set_colors(side)
  417. Side *side;
  418. {
  419.     int    t;
  420.     char *colorname, substname[BUFSIZE];
  421.     char *unseencolorname = "black";
  422.     char *gridcolorname = "black";
  423.  
  424.     side->ui->fgcolor = side->ui->foreground;
  425.     side->ui->bgcolor = side->ui->background;
  426.     side->ui->whitecolor = request_color(side, "white");
  427.     side->ui->blackcolor = request_color(side, "black");
  428.     side->ui->diffcolor = side->ui->blackcolor;
  429.     side->ui->graycolor = side->ui->whitecolor;
  430.     side->ui->enemycolor = side->ui->whitecolor;
  431.     side->ui->neutcolor = side->ui->whitecolor;
  432.     side->ui->goodcolor = side->ui->badcolor = side->ui->whitecolor;
  433.     if (!empty_string(g_grid_color()))
  434.       gridcolorname = g_grid_color();
  435.     side->ui->gridcolor =
  436.       (strcmp(gridcolorname, "white") == 0 ? side->ui->whitecolor : side->ui->blackcolor);
  437.     if (!empty_string(g_unseen_color()))
  438.       unseencolorname = g_unseen_color();
  439.     side->ui->unseencolor =
  440.       (strcmp(unseencolorname, "white") == 0 ? side->ui->whitecolor : side->ui->blackcolor);
  441.     for_all_terrain_types(t) {
  442.     if (side->ui->monochrome) {
  443.         side->ui->cellcolor[t] = side->ui->blackcolor;
  444.     } else {
  445.         colorname = t_color(t);
  446.         /* Warn if we have to substitute a valid color name. */
  447.         if (empty_string(colorname)) {
  448.         /* Substitute grays 33 to 99 only. */
  449.         sprintf(substname, "gray%d", ((t * 66) / numttypes) + 33);
  450.         init_warning("no color for terrain type \"%s\", using \"%s\"",
  451.                  t_type_name(t), substname);
  452.         colorname = substname;
  453.         }
  454.         side->ui->cellcolor[t] = request_color(side, colorname);
  455.     }
  456.     }
  457.     /* Get special-purpose colors. */
  458.     if (!side->ui->monochrome) {
  459.     side->ui->diffcolor = request_color(side, "maroon");
  460.     side->ui->graycolor = request_color(side, "light gray");
  461.     side->ui->enemycolor = request_color(side, "red");
  462.     side->ui->neutcolor = request_color(side, "gray");
  463.     side->ui->goodcolor = request_color(side, "green");
  464.     side->ui->badcolor = request_color(side, "red");
  465.     side->ui->gridcolor = request_color(side, gridcolorname);
  466.     side->ui->unseencolor = request_color(side, unseencolorname);
  467.     }
  468. }
  469.  
  470. /* A predicate that tests whether our display can safely be written to. */
  471. /* (should have a macro version for internal-to-interface use?) */
  472.  
  473. int
  474. active_display(side)
  475. Side *side;
  476. {
  477.     return (side && side->ui && side->ui->active);
  478. }
  479.  
  480. /* Set up all the GCs. */
  481.  
  482. static void
  483. init_gcs(side)
  484. Side *side;
  485. {
  486.     unsigned long mask;
  487.     XGCValues values;
  488.     GC gc;
  489.     Display *dpy = side->ui->dpy;
  490.     Window rootwin = side->ui->rootwin;
  491.  
  492.     gc = DefaultGCOfScreen(DefaultScreenOfDisplay(dpy));
  493.  
  494.     side->ui->gc = XCreateGC(dpy, rootwin, 0L, NULL);
  495.     side->ui->textgc = XCreateGC(dpy, rootwin, 0L, NULL);
  496.     side->ui->ltextgc = XCreateGC(dpy, rootwin, 0L, NULL);
  497.     side->ui->terrgc = XCreateGC(dpy, rootwin, 0L, NULL);
  498.     side->ui->unitgc = XCreateGC(dpy, rootwin, 0L, NULL);
  499.     side->ui->emblgc = XCreateGC(dpy, rootwin, 0L, NULL);
  500.     side->ui->bdrygc = XCreateGC(dpy, rootwin, 0L, NULL);
  501.  
  502.     /* Set the fonts associated with each GC. */
  503.     XSetFont(dpy, side->ui->gc, side->ui->textfont->fid);
  504.     XSetFont(dpy, side->ui->textgc, side->ui->textfont->fid);
  505.     XSetFont(dpy, side->ui->ltextgc, side->ui->textfont->fid);
  506.     if (side->ui->unitfont != NULL)
  507.       XSetFont(dpy, side->ui->unitgc, side->ui->unitfont->fid);
  508.  
  509.     /* Set misc properties of each GC. */
  510.     mask = GCFillStyle | GCGraphicsExposures;
  511.     values.fill_style = FillSolid;
  512.     values.graphics_exposures = FALSE;
  513.     XChangeGC(dpy, side->ui->terrgc, mask, &values);
  514.     XChangeGC(dpy, side->ui->unitgc, mask, &values);
  515.     XChangeGC(dpy, side->ui->emblgc, mask, &values);
  516.     XChangeGC(dpy, side->ui->bdrygc, mask, &values);
  517.  
  518.     DGprintf("GCs stored ...\n");
  519. }
  520.  
  521. /* Set up all the fonts. */
  522.  
  523. static void
  524. init_fonts(side)
  525. Side *side;
  526. {
  527.     int p, u;
  528.     XFontStruct *font;
  529.  
  530.     side->ui->textfont =
  531.       open_font(side, TEXTFONT, "TextFont", NULL, "", NULL);
  532.     side->ui->fw = font_width(side->ui->textfont);
  533.     side->ui->fh = font_height(side->ui->textfont);
  534.     font =
  535.       open_font(side, "*-bold-r-*-10-*", "LegendFont",
  536.         side->ui->textfont, "text", NULL);
  537.     for (p = 0; p < NUMPOWERS; ++p) {
  538.     for_all_unit_types(u) {
  539.         side->ui->ulegendfonts[p][u] = font;
  540.     }
  541.     }
  542.     side->ui->flegendfonts[0] =
  543.       open_font(side, "-*-helvetica-medium-r-*-*-8-*-*-*-*-*-*-*",
  544.         "LegendFont0", side->ui->textfont, "text",
  545.         &side->ui->flegendfids[0]);
  546.     side->ui->flegendfonts[1] =
  547.       open_font(side, "-*-helvetica-medium-r-*-*-10-*-*-*-*-*-*-*",
  548.         "LegendFont1", side->ui->textfont, "text",
  549.         &side->ui->flegendfids[1]);
  550.     side->ui->flegendfonts[2] =
  551.       open_font(side, "-*-helvetica-medium-r-*-*-14-*-*-*-*-*-*-*",
  552.         "LegendFont2", side->ui->textfont, "text",
  553.         &side->ui->flegendfids[2]);
  554.     side->ui->flegendfonts[3] =
  555.       open_font(side, "-*-helvetica-medium-r-*-*-18-*-*-*-*-*-*-*",
  556.         "LegendFont3", side->ui->textfont, "text",
  557.         &side->ui->flegendfids[3]);
  558.     side->ui->flegendfonts[4] =
  559.       open_font(side, "-*-helvetica-medium-r-*-*-24-*-*-*-*-*-*-*",
  560.         "LegendFont4", side->ui->textfont, "text",
  561.         &side->ui->flegendfids[4]);
  562.     DGprintf("Fonts opened ...\n");
  563. }
  564.  
  565. /* Get a color set up and warn if not getting what was asked for.  We can */
  566. /* tolerate being off somewhat.  (Note X rgb value range is 0-65535.) */
  567.  
  568. #define CLOSE_ENOUGH(X,Y) (ABS(((int) X) - ((int) Y)) < 2000)
  569.  
  570. long
  571. request_color(side, name)
  572. Side *side;
  573. char *name;
  574. {
  575.     XColor c, avail;
  576.  
  577.     DGprintf("Requesting color %s\n", (name ? name : "<null>"));
  578.     /* This might be called to get user-specified colors, even on a mono
  579.        display, so deal with it. */
  580.     if (empty_string(name)) {
  581.     init_warning(
  582.           "Requesting anonymous color on display \"%s\", substituting white",
  583.              side->player->displayname);
  584.     return WhitePixel(side->ui->dpy, side->ui->screen);
  585.     } else if (side->ui->monochrome) {
  586.     if (strcmp("white", name) == 0) {
  587.         return WhitePixel(side->ui->dpy, side->ui->screen);
  588.     } else if (strcmp("black", name) == 0) {
  589.         return BlackPixel(side->ui->dpy, side->ui->screen);
  590.     } else {
  591.         init_warning(
  592.               "No color \"%s\" on the mono display \"%s\", substituting white",
  593.              name, side->player->displayname);
  594.         return WhitePixel(side->ui->dpy, side->ui->screen);
  595.     }
  596.     } else {
  597.     XAllocNamedColor(side->ui->dpy,
  598.              DefaultColormap(side->ui->dpy, side->ui->screen),
  599.              name, &avail, &c);
  600.     if (!(CLOSE_ENOUGH(c.red, avail.red)
  601.           && CLOSE_ENOUGH(c.green, avail.green)
  602.           && CLOSE_ENOUGH(c.blue, avail.blue))) {
  603.         init_warning("%s color is way off on display \"%s\"!",
  604.              name, side->player->displayname);
  605.         init_warning("(%d %d %d instead of %d %d %d), but using it anyway",
  606.              avail.red, avail.green, avail.blue,
  607.              c.red, c.green, c.blue);
  608.     }
  609.     return avail.pixel;
  610.     }
  611. }
  612.  
  613. static void
  614. init_bitmaps(side)
  615. Side *side;
  616. {
  617.     int i;
  618.     Display *dpy = side->ui->dpy;
  619.     Window win = side->ui->rootwin;
  620.  
  621.     /* Get the solid hex outlines. */
  622.     side->ui->hexpics[3] =
  623.       XCreateBitmapFromData(dpy, win, hex8_bits, hex8_width, hex8_height);
  624.     side->ui->bhexpics[3] =
  625.       XCreateBitmapFromData(dpy, win, hex8b_bits, hex8b_width, hex8b_height);
  626.     side->ui->hexpics[4] =
  627.       XCreateBitmapFromData(dpy, win, hex16_bits, hex16_width, hex16_height);
  628.     side->ui->bhexpics[4] =
  629.       XCreateBitmapFromData(dpy, win, hex16b_bits, hex16b_width, hex16b_height);
  630.     side->ui->hexpics[5] =
  631.       XCreateBitmapFromData(dpy, win, hex32_bits, hex32_width, hex32_height);
  632.     side->ui->bhexpics[5] =
  633.       XCreateBitmapFromData(dpy, win, hex32b_bits, hex32b_width, hex32b_height);
  634.     /* Get pictures of mushroom clouds. */
  635.     side->ui->bombpics[0] =
  636.       XCreateBitmapFromData(dpy, win, bomb1_bits, bomb1_width, bomb1_height);
  637.     side->ui->bombpics[1] =
  638.       XCreateBitmapFromData(dpy, win, bomb2_bits, bomb2_width, bomb2_height);
  639.     side->ui->bombpics[2] =
  640.       XCreateBitmapFromData(dpy, win, bomb3_bits, bomb3_width, bomb3_height);
  641.     side->ui->bombpics[3] =
  642.       XCreateBitmapFromData(dpy, win, bomb4_bits, bomb4_width, bomb4_height);
  643.     side->ui->hitpics[0] =
  644.       XCreateBitmapFromData(dpy, win, miss_bits, miss_width, miss_height);
  645.     side->ui->hitpics[1] =
  646.       XCreateBitmapFromData(dpy, win, hit_bits, hit_width, hit_height);
  647.     side->ui->hitpics[2] =
  648.       XCreateBitmapFromData(dpy, win, kill_bits, kill_width, kill_height);
  649.     side->ui->boxcurs =
  650.       XCreateBitmapFromData(dpy, win, boxcurs_bits, boxcurs_width, boxcurs_height);
  651.     side->ui->boxmask =
  652.       XCreateBitmapFromData(dpy, win, boxmask_bits, boxmask_width, boxmask_height);
  653.     side->ui->grays[gray] =
  654.       XCreateBitmapFromData(dpy, win, gray_bits, gray_width, gray_height);
  655.     side->ui->grays[darkgray] =
  656.       XCreateBitmapFromData(dpy, win, darkgray_bits, darkgray_width, darkgray_height);
  657.     /* Collect pictures that will be used with map controls. */
  658.     for (i = 0; i < numcontrols; ++i)
  659.       side->ui->controlpics[i] = None;
  660.     side->ui->controlpics[LOOK] =
  661.       XCreateBitmapFromData(dpy, win, lookglass_bits, 16, 16);
  662.     side->ui->controlpics[MOVE] =
  663.       XCreateBitmapFromData(dpy, win, shootcursor_bits, 16, 16);
  664.     side->ui->controlpics[UNIT_MOVE] =
  665.       XCreateBitmapFromData(dpy, win, movecursor_bits, 16, 16);
  666.     side->ui->controlpics[UNIT_SHOOT] =
  667.       XCreateBitmapFromData(dpy, win, shootcursor_bits, 16, 16);
  668.     side->ui->controlpics[UNIT_BUILD] =
  669.       XCreateBitmapFromData(dpy, win, buildcursor_bits, 16, 16);
  670.     side->ui->controlpics[ZOOM_OUT] =
  671.       XCreateBitmapFromData(dpy, win, farther_bits, 16, 16);
  672.     side->ui->controlpics[ZOOM_IN] =
  673.       XCreateBitmapFromData(dpy, win, closer_bits, 16, 16);
  674.     DGprintf("Bitmaps stored ...\n");
  675. }
  676.  
  677. /* Make all the different kinds of cursors we intend to use.  Should be
  678.    one for each kind of mode or tool.  Cursors should always be 16x16. */
  679.  
  680. static void
  681. init_cursors(side)
  682. Side *side;
  683. {
  684.     int i;
  685.     Display *dpy = side->ui->dpy;
  686.     Window win = side->ui->rootwin;
  687.     int fg = side->ui->fgcolor, bg = side->ui->bgcolor;
  688.  
  689.     for (i = 0; i < numtools; ++i)
  690.       side->ui->toolcursors[i] = None;
  691.     side->ui->toolcursors[looktool] =
  692.       make_cursor(dpy, win, lookglass_bits, lookmask_bits,
  693.           fg, bg, lookglass_x_hot, lookglass_y_hot);
  694.     side->ui->toolcursors[movetool] =
  695.       make_cursor(dpy, win, shootcursor_bits, shootmask_bits,
  696.           fg, bg, shootcursor_x_hot, shootcursor_y_hot);
  697.     side->ui->toolcursors[unitmovetool] =
  698.       make_cursor(dpy, win, movecursor_bits, movemask_bits,
  699.           fg, bg, movecursor_x_hot, movecursor_y_hot);
  700.     side->ui->toolcursors[unitshoottool] =
  701.       make_cursor(dpy, win, shootcursor_bits, shootmask_bits,
  702.           fg, bg, shootcursor_x_hot, shootcursor_y_hot);
  703.     side->ui->toolcursors[unitbuildtool] =
  704.       make_cursor(dpy, win, buildcursor_bits, buildmask_bits,
  705.           fg, bg, buildcursor_x_hot, buildcursor_y_hot);
  706. #ifdef DESIGNERS
  707.     side->ui->toolcursors[cellpainttool] =
  708.       make_cursor(dpy, win, hexcursor_bits, hexcursormask_bits,
  709.           fg, bg, hexcursor_x_hot, hexcursor_y_hot);
  710.     side->ui->toolcursors[bordpainttool] =
  711.       make_cursor(dpy, win, bordcursor_bits, bordcursor_bits, /* should have separate mask */
  712.           fg, bg, bordcursor_x_hot, bordcursor_y_hot);
  713.     side->ui->toolcursors[connpainttool] =
  714.       make_cursor(dpy, win, conncursor_bits, conncursor_bits, /* should have separate mask */
  715.           fg, bg, conncursor_x_hot, conncursor_y_hot);
  716.     side->ui->toolcursors[unitaddtool] =
  717.       make_cursor(dpy, win, addunits_bits, addunits_bits,
  718.           fg, bg, addunits_x_hot, addunits_y_hot);
  719.     side->ui->toolcursors[peoplepainttool] =
  720.       make_cursor(dpy, win, people_bits, people_bits,
  721.           fg, bg, people_x_hot, people_y_hot);
  722.     side->ui->toolcursors[featurepainttool] =
  723.       make_cursor(dpy, win, feature_bits, featuremask_bits,
  724.           fg, bg, feature_x_hot, feature_y_hot);
  725. #endif /* DESIGNERS */
  726.     DGprintf("Cursors stored ...\n");
  727. }
  728.  
  729. /* Since XCreatePixmapCursor() takes XColors and not pixel values we
  730.    have to look up the colors associated with the foreground and
  731.    background pixel values in the color table and pass them to
  732.    XCreatePixmapCursor(). */
  733.    
  734. Cursor
  735. make_cursor(dpy, win, cursbits, maskbits, fg, bg, x, y)
  736. Display *dpy;
  737. Window win;
  738. char *cursbits, *maskbits;
  739. unsigned long fg, bg;
  740. unsigned int x, y;
  741. {
  742.     Pixmap curs, mask;
  743.     XColor fgcolor, bgcolor;
  744.     Cursor rslt;
  745.  
  746.     mask = XCreateBitmapFromData(dpy, win, maskbits, 16, 16);
  747.     curs = XCreateBitmapFromData(dpy, win, cursbits, 16, 16);
  748.     fgcolor.pixel = fg;
  749.     XQueryColor(dpy, DefaultColormap(dpy, DefaultScreen(dpy)), &fgcolor);
  750.     bgcolor.pixel = bg;
  751.     XQueryColor(dpy, DefaultColormap(dpy, DefaultScreen(dpy)), &bgcolor);
  752.     rslt = XCreatePixmapCursor(dpy, curs, mask, &fgcolor, &bgcolor, x, y);
  753.     XFreePixmap(dpy, mask);
  754.     XFreePixmap(dpy, curs);
  755.     return rslt;
  756. }
  757.  
  758. /* Open a font, possibly substituting another font if our desired one is
  759.    missing for some reason. */
  760.  
  761. XFontStruct *
  762. open_font(side, name, xdefault, altfont, alttype, fid)
  763. Side *side;
  764. char *name, *xdefault, *alttype;
  765. XFontStruct *altfont;
  766. Font *fid;
  767. {
  768.     XFontStruct *font;
  769.  
  770.     if (fid) {
  771.     *fid = XLoadFont(side->ui->dpy, name);
  772.     font = XQueryFont(side->ui->dpy, *fid);
  773.     } else {
  774.     font = XLoadQueryFont(side->ui->dpy, name);
  775.     }
  776.     if (font == NULL) {
  777.     init_warning("Can't open font \"%s\" on \"%s\"",
  778.              name, side->player->displayname);
  779.     if (altfont != NULL) {
  780.         init_warning("Substituting the %s font, hope it works!", alttype);
  781.         return altfont;
  782.     } else {
  783.         return NULL;
  784.     }
  785.     }
  786.     DGprintf("Opened font \"%s\" ...\n", name);
  787.     return font;
  788. }
  789.  
  790. /* Get a total bounding box on the font. */
  791.  
  792. int
  793. font_width(font)
  794. XFontStruct *font;
  795. {
  796.     return font->max_bounds.width;
  797. }
  798.  
  799. int
  800. font_height(font)
  801. XFontStruct *font;
  802. {
  803.     return font->max_bounds.ascent + font->max_bounds.descent;
  804. }
  805.  
  806. static void
  807. x11_interp_fn(imf)
  808. ImageFamily *imf;
  809. {
  810.     x11_interp_imf(tmp_display, tmp_root_window, imf, FALSE);
  811. }
  812.  
  813. static void
  814. x11_load_fn(imf)
  815. ImageFamily *imf;
  816. {
  817.     x11_load_imf(tmp_display, tmp_root_window, imf);
  818. }
  819.  
  820. static void
  821. init_unit_images(side)
  822. Side *side;
  823. {
  824.     int u, w, h;
  825.     ImageFamily *imf;
  826.  
  827.     side->ui->uimages =
  828.       (ImageFamily **) xmalloc(numutypes * sizeof(ImageFamily *));
  829.     tmp_display = side->ui->dpy;
  830.     tmp_root_window = side->ui->rootwin;
  831.     for_all_unit_types(u) {
  832.     imf = get_unit_type_images(side, u, x11_interp_fn, x11_load_fn, NULL);
  833.     /* (should fabricate something as a substitute) */
  834.     if (DebugG)
  835.       describe_imf(side, "unit type", u_type_name(u), imf);
  836.     side->ui->uimages[u] = imf;
  837.     if (smallest_image(imf, &w, &h)) {
  838.         if (w > min_w_for_unit_image)
  839.           min_w_for_unit_image = w;
  840.         if (h > min_h_for_unit_image)
  841.           min_h_for_unit_image = h;
  842.     }
  843.     }
  844. }
  845.  
  846. /* Collect images for all the terrain types. */
  847.  
  848. static void
  849. init_terrain_images(side)
  850. Side *side;
  851. {
  852.     int t, p;
  853.     ImageFamily *imf;
  854.     Image *timg;
  855.     X11Image *ximg;
  856.  
  857.     side->ui->timages =
  858.       (ImageFamily **) xmalloc(numttypes * sizeof(ImageFamily *));
  859.     tmp_display = side->ui->dpy;
  860.     tmp_root_window = side->ui->rootwin;
  861.     for_all_terrain_types(t) {
  862.     imf = get_terrain_type_images(side, t, x11_interp_fn, x11_load_fn, NULL);
  863.     if (imf != NULL && imf->numsizes == 0)
  864.       get_default_terrain_image(side, imf, t);
  865.     if (DebugG)
  866.       describe_imf(side, "terrain type", t_type_name(t), imf);
  867.     side->ui->timages[t] = imf;
  868.     /* Precalculate which images to use at which magnifications. */
  869.     for (p = 0; p < NUMPOWERS; ++p) {
  870.         if (1) {
  871.         timg = best_image(side->ui->timages[t], hws[p], hhs[p]);
  872.         if (timg != NULL) {
  873.             ximg = (X11Image *) timg->hook;
  874.             if (ximg != NULL) {
  875.             if (!side->ui->monochrome
  876. /* if somebody changes their mind about using the color images, this will lose */
  877.                  && side->ui->dflt_color_terr_images
  878.                  && ximg->colr != None)
  879.               side->ui->terrpics[p][t] = ximg->colr;
  880.             else
  881.               side->ui->terrpics[p][t] = ximg->mono;
  882.             }
  883.         }
  884.         }
  885.     }
  886.     }
  887. }
  888.  
  889. static void
  890. get_default_terrain_image(side, imf, t)
  891. Side *side;
  892. ImageFamily *imf;
  893. int t;
  894. {
  895.     Image *img;
  896.     X11Image *ximg;
  897.  
  898.     img = get_img(imf, 20, 22);
  899.     img->minw = 1;  img->minh = 1;
  900.     img->maxw = 999;  img->maxh = 999;
  901.     ximg = get_x11_image(img);
  902.     ximg->mono = 
  903.       XCreateBitmapFromData(side->ui->dpy, side->ui->rootwin,
  904.                 hex16b_bits, hex16b_width, hex16b_height);
  905. }
  906.  
  907. /* Set up a side's view of everybody else's colors and emblems. */
  908.  
  909. static void
  910. init_emblem_images(side)
  911. Side *side;
  912. {
  913.     Side *side2;
  914.     
  915.     side->ui->eimages =
  916.       (ImageFamily **) xmalloc((numsides + 1) * sizeof(ImageFamily *));
  917.     /* Independent units may have a distinguishing emblem, so the
  918.        indepside is included here. */
  919.     for_all_sides_plus_indep(side2) {
  920.     init_emblem(side, side2);
  921.     }
  922. }
  923.  
  924. /* Compute the distinctive emblem by which one side will recognize units
  925.    of another side.  This does both our view of ourselves and others
  926.    orthogonally.  Note that sides without displays can still have emblems
  927.    and colors that the sides with displays will see, but that sides
  928.    without displays don't need to do any emblem init. */
  929.  
  930. static void
  931. init_emblem(side, side2)
  932. Side *side, *side2;
  933. {
  934.     char cbuf[BUFSIZ], *s, *c;
  935.     int s2 = side_number(side2), i;
  936.     ImageFamily *imf;
  937.  
  938.     /* Collect the color names of the other side and try to request
  939.        them for our own display. */
  940.     if (!side->ui->monochrome && !empty_string(side2->colorscheme)) {
  941.     /* take spec apart and iterate for multiple colors */
  942.     for (s = side2->colorscheme, c = cbuf, i = 0; i < 3; ++s) {
  943.         if (*s == ',' || *s == '\0') {
  944.         *c = '\0';
  945.         c = cbuf;
  946.         side->ui->colors[s2][i++] = request_color(side, cbuf);
  947.         } else {
  948.         *c++ = *s;
  949.         }
  950.         if (*s == '\0')
  951.           break;
  952.     }
  953.     side->ui->numcolors[s2] = i;
  954.     } else {
  955.     side->ui->numcolors[s2] = 0;
  956.     }
  957.     tmp_display = side->ui->dpy;
  958.     tmp_root_window = side->ui->rootwin;
  959.     imf = get_emblem_images(side, side2, x11_interp_fn, x11_load_fn, NULL);
  960.     if (imf != NULL
  961.     && imf->numsizes == 0
  962.     && !(imf->name != NULL && strcmp(imf->name, "none") == 0)) {
  963.     get_default_emblem(side, imf, side2);
  964.     }
  965.     if (DebugG)
  966.       describe_imf(side, "emblem", side_desig(side2), imf);
  967.     side->ui->eimages[s2] = imf;
  968. }
  969.  
  970. static void
  971. get_default_emblem(side, imf, side2)
  972. Side *side, *side2;
  973. ImageFamily *imf;
  974. {
  975.     Image *img;
  976.     X11Image *ximg;
  977.  
  978.     img = get_img(imf, 8, 8);
  979.     img->minw = 8;  img->minh = 8;
  980.     img->maxw = 128;  img->maxh = 128;
  981.     ximg = get_x11_image(img);
  982.     /* (should make something for this image) */
  983. }
  984.  
  985. /* Output a general description of an image family. */
  986.  
  987. static void
  988. describe_imf(side, classname, typename, imf)
  989. Side *side;
  990. char *classname, *typename;
  991. ImageFamily *imf;
  992. {
  993.     Image *img;
  994.     X11Image *ximg;
  995.  
  996.     if (imf == NULL) {
  997.     DGprintf("No image family for %s %s for %s",
  998.          classname, typename, side_desig(side));
  999.     return;
  1000.     }
  1001.     DGprintf("%s %s family for %s has %d images",
  1002.          classname, typename, side_desig(side), imf->numsizes);
  1003.     if (imf->location)
  1004.       DGprintf(" and is in %s", imf->location->name);
  1005.     DGprintf("\n");
  1006.     for (img = imf->images; img != NULL; img = img->next) {
  1007.     DGprintf("    %dx%d", img->w, img->h);
  1008.     ximg = (X11Image *) img->hook;
  1009.     if (ximg)
  1010.       DGprintf(" (x11 mono %d color %d mask %d)", ximg->mono, ximg->colr, ximg->mask);
  1011.     DGprintf("\n");
  1012.     }
  1013. }
  1014.  
  1015. void 
  1016. popup_game_dialog ()
  1017. {
  1018.     int i;
  1019.     Widget outform, label, quit, viewp, inform;
  1020.     Module *module;
  1021.     
  1022.     games = (Gamew *) xmalloc(numgames*sizeof(Gamew));
  1023.     
  1024.     gameShell =
  1025.       XtVaCreatePopupShell("gameDialog", topLevelShellWidgetClass, thistoplevel,
  1026.                NULL);
  1027.     outform =
  1028.       XtVaCreateManagedWidget("outForm", formWidgetClass, gameShell,
  1029.                   NULL);
  1030.     label =
  1031.       XtVaCreateManagedWidget("label", labelWidgetClass, outform,
  1032.                   XtNtop,    XawChainTop, 
  1033.                   XtNbottom, XawChainTop, 
  1034.                   XtNleft,   XawChainLeft, 
  1035.                   XtNright,  XawChainLeft,
  1036.                   NULL);
  1037.     quit =
  1038.       XtVaCreateManagedWidget("quit", commandWidgetClass, outform,
  1039.                   XtNfromHoriz, label,
  1040.                   XtNtop,    XawChainTop, 
  1041.                   XtNbottom, XawChainTop, 
  1042.                   XtNleft,   XawChainLeft, 
  1043.                   XtNright,  XawChainLeft,
  1044.                   NULL);
  1045.     XtAddCallback (quit, XtNcallback, quit_dialog, NULL);
  1046.  
  1047.     viewp =
  1048.       XtVaCreateManagedWidget("viewport", viewportWidgetClass,  outform,
  1049.                   XtNfromVert,  label,
  1050.                   XtNallowVert, True,
  1051.                   XtNtop,    XawChainTop, 
  1052.                   XtNbottom, XawChainBottom, 
  1053.                   XtNleft,   XawChainLeft, 
  1054.                   XtNright,  XawChainRight,
  1055.                   NULL);
  1056.     inform =
  1057.       XtVaCreateManagedWidget("inForm", formWidgetClass, viewp,
  1058.                   NULL);
  1059.     
  1060.     for (i = 0; i < numgames; ++i) {
  1061.     module = possible_games[i];
  1062.     games[i].form =
  1063.       XtVaCreateManagedWidget(module->name, formWidgetClass, inform, 
  1064.                   XtNfromVert, i ? games[i-1].form : NULL,
  1065.                   XtNtop,    XawChainTop, 
  1066.                   XtNbottom, XawChainTop, 
  1067.                   XtNleft,   XawChainLeft, 
  1068.                   XtNright,  XawChainLeft,
  1069.                   NULL);
  1070.     games[i].name =
  1071.       XtVaCreateManagedWidget("name", commandWidgetClass, games[i].form,
  1072.                   XtNlabel, module->name,
  1073.                   XtNtop,    XawChainTop, 
  1074.                   XtNbottom, XawChainTop, 
  1075.                   XtNleft,   XawChainLeft, 
  1076.                   XtNright,  XawChainLeft,
  1077.                   NULL);
  1078.     XtAddCallback (games[i].name, XtNcallback, game_callback, NULL);
  1079.     if (module->title && module->title[0]) {
  1080.         games[i].title =
  1081.           XtVaCreateManagedWidget("title", labelWidgetClass, games[i].form,
  1082.                       XtNlabel, module->title,
  1083.                       XtNfromHoriz, games[i].name,
  1084.                       XtNtop,    XawChainTop, 
  1085.                       XtNbottom, XawChainTop, 
  1086.                       XtNleft,   XawChainLeft, 
  1087.                       XtNright,  XawChainLeft,
  1088.                       NULL);
  1089.     } else {
  1090.         games[i].title = NULL;
  1091.     }
  1092.     if (module->blurb && module->blurb[0]) {
  1093.         games[i].blurb =
  1094.           XtVaCreateManagedWidget("blurb", labelWidgetClass, games[i].form,
  1095.                       XtNlabel, module->blurb,
  1096.                       XtNfromHoriz,
  1097.                       games[i].title ? games[i].title : games[i].name,
  1098.                       XtNtop,    XawChainTop, 
  1099.                       XtNbottom, XawChainTop, 
  1100.                       XtNleft,   XawChainLeft, 
  1101.                       XtNright,  XawChainLeft,
  1102.                       NULL);
  1103.     } else {
  1104.         games[i].blurb = NULL;
  1105.     }
  1106.     games[i].pop = NULL;
  1107.     }
  1108.     
  1109.     XtPopup(gameShell, XtGrabNone);
  1110.     
  1111.     /* replacement for XtAppMainLoop(thisapp): */
  1112.     loop = 1;
  1113.     while (loop) {
  1114.     XEvent event;
  1115.  
  1116.     XtAppNextEvent(thisapp, &event);
  1117.     XtDispatchEvent(&event);
  1118.     }
  1119. }
  1120.  
  1121. static void
  1122. popup_game(g, flag)
  1123. int g, flag;
  1124. {
  1125.     char *vartypename = NULL;
  1126.     GamePop *pop = games[g].pop;
  1127.     Module *module = possible_games[g];
  1128.     Widget up, left, save;
  1129.     Variant *var;
  1130.     Varw *varw;
  1131.     int i;
  1132.     Side *side;
  1133.     Player *player;
  1134.     static char *player_type[] = { "none", "human", "machine" };
  1135.     Widget pane;
  1136.  
  1137.     if (!pop || flag) {
  1138.     if (!pop) {
  1139.         games[g].pop = pop = (GamePop *) xmalloc(sizeof(GamePop));
  1140.         pop->variants = NULL;
  1141.     }
  1142.     sprintf(buf1, "xconq game: %s", module->name);
  1143.     pop->shell =
  1144.       XtVaCreatePopupShell(module->name, topLevelShellWidgetClass,
  1145.                    thistoplevel, 
  1146.                    XtNtitle, buf1,
  1147.                    NULL);
  1148.     pop->form =
  1149.       XtVaCreateManagedWidget("gameForm", formWidgetClass, pop->shell,
  1150.                   NULL);
  1151.     up = left = pop->name =
  1152.       XtVaCreateManagedWidget("name", labelWidgetClass, pop->form,
  1153.                   XtNlabel, module->name,
  1154.                   XtNtop,    XawChainTop, 
  1155.                   XtNbottom, XawChainTop, 
  1156.                   XtNleft,   XawChainLeft, 
  1157.                   XtNright,  XawChainLeft,
  1158.                   NULL);
  1159.     if (module->basemodulename && module->basemodulename[0]) {
  1160.         sprintf(buf1, "base module: %s", module->basemodulename);
  1161.     } else {
  1162.         strcpy(buf1, "no base module");
  1163.     }
  1164.     left = pop->basemodule =
  1165.       XtVaCreateManagedWidget("basemodule", labelWidgetClass, pop->form,
  1166.                   XtNlabel, buf1,
  1167.                   XtNfromHoriz, left,
  1168.                   XtNtop,    XawChainTop, 
  1169.                   XtNbottom, XawChainTop, 
  1170.                   XtNleft,   XawChainLeft, 
  1171.                   XtNright,  XawChainLeft,
  1172.                   NULL);
  1173.     if (module->version && module->version[0]) {
  1174.         sprintf(buf1, "version: %s", module->version);
  1175.         left = pop->version =
  1176.           XtVaCreateManagedWidget("version", labelWidgetClass, pop->form,
  1177.                       XtNlabel, module->version,
  1178.                       XtNfromHoriz, left,
  1179.                       XtNtop,    XawChainTop, 
  1180.                       XtNbottom, XawChainTop, 
  1181.                       XtNleft,   XawChainLeft, 
  1182.                       XtNright,  XawChainLeft,
  1183.                       NULL);
  1184.     }
  1185.     if (module->title && module->title[0]) {
  1186.         up = pop->title =
  1187.           XtVaCreateManagedWidget("title", labelWidgetClass, pop->form,
  1188.                       XtNlabel, module->title,
  1189.                       XtNfromVert, pop->name,
  1190.                       XtNtop,    XawChainTop, 
  1191.                       XtNbottom, XawChainTop, 
  1192.                       XtNleft,   XawChainLeft, 
  1193.                       XtNright,  XawChainLeft,
  1194.                       NULL);
  1195.     }
  1196.     if (module->blurb && module->blurb[0]) {
  1197.         up = pop->blurb =
  1198.           XtVaCreateManagedWidget("blurb", labelWidgetClass, pop->form,
  1199.                       XtNlabel, module->blurb,
  1200.                       XtNfromHoriz, pop->title,
  1201.                       XtNfromVert, pop->name,
  1202.                       XtNtop,    XawChainTop, 
  1203.                       XtNbottom, XawChainTop, 
  1204.                       XtNleft,   XawChainLeft, 
  1205.                       XtNright,  XawChainLeft,
  1206.                       NULL);
  1207.     }
  1208.  
  1209.     if (module->variants) {
  1210.         for (i = 0; module->variants[i].id != lispnil; ++i) { }
  1211.         pop->numvariants = i;
  1212.     } else {
  1213.         pop->numvariants = 0;
  1214.     }
  1215.     if (flag && pop->numvariants) {
  1216.         if (flag == 1) {
  1217.         pop->variants =
  1218.           (Varw *) xmalloc(pop->numvariants*sizeof(Varw));
  1219.         }
  1220.         up =
  1221.           XtVaCreateManagedWidget("variant", labelWidgetClass, pop->form,
  1222.                       XtNlabel, "Variants:",
  1223.                       XtNfromVert, up,
  1224.                       XtNtop,    XawChainTop, 
  1225.                       XtNbottom, XawChainTop, 
  1226.                       XtNleft,   XawChainLeft, 
  1227.                       XtNright,  XawChainLeft,
  1228.                       NULL);
  1229.  
  1230.         for (i = 0; i < pop->numvariants; ++i) {
  1231.         var = &(module->variants[i]);
  1232.         varw = &(pop->variants[i]);
  1233.         vartypename = c_string(var->id);
  1234.  
  1235.         if (flag == 1)
  1236.           varw->value = variant_default(var); 
  1237.         sprintf(buf1, "variant%d", i);
  1238.         up = varw->dialog =
  1239.           XtVaCreateManagedWidget(buf1, dialogWidgetClass, pop->form,
  1240.                       XtNlabel, variant_name(var),
  1241.                       XtNvalue, varw->value,
  1242.                       XtNfromVert, up,
  1243.                       XtNtop,    XawChainTop, 
  1244.                       XtNbottom, XawChainTop, 
  1245.                       XtNleft,   XawChainLeft, 
  1246.                       XtNright,  XawChainLeft,
  1247.                       NULL);
  1248.         horizontalDialog(varw->dialog);
  1249.         if (varw->mess && varw->mess[0]) {
  1250.             reverseVideoDialog(varw->dialog);
  1251.             up =
  1252.               XtVaCreateManagedWidget("varMessage", labelWidgetClass,
  1253.                           pop->form,
  1254.                           XtNlabel, varw->mess,
  1255.                           XtNfromVert, up,
  1256.                           XtNtop,    XawChainTop, 
  1257.                           XtNbottom, XawChainTop, 
  1258.                           XtNleft,   XawChainLeft, 
  1259.                           XtNright,  XawChainLeft,
  1260.                           NULL);
  1261.         }
  1262.         }
  1263.     }
  1264.  
  1265.     if (module->instructions != lispnil ||
  1266.         module->notes != lispnil) {
  1267.         up = pane =
  1268.           XtVaCreateManagedWidget("pane", panedWidgetClass, pop->form,
  1269.                       XtNfromVert, up,
  1270.                       XtNorientation, XtorientVertical,
  1271.                       XtNtop,    XawChainTop, 
  1272.                       XtNbottom, XawChainBottom, 
  1273.                       XtNleft,   XawChainLeft, 
  1274.                       XtNright,  XawChainRight,
  1275.                       NULL);
  1276.         pop->instructions =
  1277.           createTextWidget("instructions", pane,
  1278.                    NULL, module->instructions);
  1279.         pop->notes =
  1280.           createTextWidget("notes", pane,
  1281.                    pop->instructions, module->notes);
  1282.         
  1283.     }
  1284.     if (flag) {
  1285.         up = XtVaCreateManagedWidget("assign", labelWidgetClass, pop->form,
  1286.                      XtNlabel, "Assignments:",
  1287.                      XtNfromVert, up,
  1288.                      XtNtop,    XawChainBottom, 
  1289.                      XtNbottom, XawChainBottom, 
  1290.                      XtNleft,   XawChainLeft, 
  1291.                      XtNright,  XawChainLeft,
  1292.                      NULL);
  1293.         if (flag == 1) {
  1294.         pop->assign = (Assignw *) xmalloc(MAXSIDES*sizeof(Assignw));
  1295.         }
  1296.         for (i = 0; i < numsides; ++i) {
  1297.         side   = assignments[i].side;
  1298.         player = assignments[i].player;
  1299.         if (flag == 1) { 
  1300.             init_assignw_player(&(pop->assign[i]), player);
  1301.         }
  1302.         if (side->sideclass && side->sideclass[0]) {
  1303.             sprintf(buf1, "%s (%s)", short_side_title(side),
  1304.                 side->sideclass);
  1305.         } else {
  1306.             strcpy(buf1, short_side_title(side));
  1307.         }
  1308.         save = left = pop->assign[i].sidew =
  1309.           XtVaCreateManagedWidget("side", labelWidgetClass, pop->form,
  1310.                       XtNlabel, buf1,
  1311.                       XtNfromVert, up,
  1312.                       XtNtop,    XawChainBottom, 
  1313.                       XtNbottom, XawChainBottom, 
  1314.                       XtNleft,   XawChainLeft, 
  1315.                       XtNright,  XawChainLeft,
  1316.                       NULL);
  1317.         left = pop->assign[i].pname =
  1318.           XtVaCreateManagedWidget("pname", dialogWidgetClass,
  1319.                       pop->form,
  1320.                       XtNlabel, "name",
  1321.                       XtNvalue, pop->assign[i].vname,
  1322.                       XtNfromHoriz, left,
  1323.                       XtNfromVert, up,
  1324.                       XtNtop,    XawChainBottom, 
  1325.                       XtNbottom, XawChainBottom, 
  1326.                       XtNleft,   XawChainLeft, 
  1327.                       XtNright,  XawChainLeft,
  1328.                       NULL);
  1329.         horizontalDialog(pop->assign[i].pname);
  1330.         up = pop->assign[i].pid =
  1331.           XtVaCreateManagedWidget("pid", dialogWidgetClass, pop->form,
  1332.                       XtNlabel, player_type[pop->assign[i].vflag],
  1333.                       XtNvalue, pop->assign[i].vid,
  1334.                       XtNfromHoriz, left,
  1335.                       XtNfromVert, up,
  1336.                       XtNtop,    XawChainBottom, 
  1337.                       XtNbottom, XawChainBottom, 
  1338.                       XtNleft,   XawChainLeft, 
  1339.                       XtNright,  XawChainLeft,
  1340.                       NULL);
  1341.         horizontalDialog(pop->assign[i].pid);
  1342.         if (pop->assign[i].messname && pop->assign[i].messname[0]) {
  1343.             reverseVideoDialog(pop->assign[i].pname);
  1344.             up = XtVaCreateManagedWidget("nameMessage",
  1345.                          labelWidgetClass, pop->form,
  1346.                          XtNlabel, pop->assign[i].messname,
  1347.                          XtNfromHoriz, save,
  1348.                          XtNfromVert, up,
  1349.                          XtNtop,    XawChainBottom, 
  1350.                          XtNbottom, XawChainBottom, 
  1351.                          XtNleft,   XawChainLeft, 
  1352.                          XtNright,  XawChainLeft,
  1353.                          NULL);
  1354.         }
  1355.         if (pop->assign[i].messid && pop->assign[i].messid[0]) {
  1356.             reverseVideoDialog(pop->assign[i].pid);
  1357.             up = XtVaCreateManagedWidget("idMessage",
  1358.                          labelWidgetClass, pop->form,
  1359.                          XtNlabel, pop->assign[i].messid,
  1360.                          XtNfromHoriz, save,
  1361.                          XtNfromVert, up,
  1362.                          XtNtop,    XawChainBottom, 
  1363.                          XtNbottom, XawChainBottom, 
  1364.                          XtNleft,   XawChainLeft, 
  1365.                          XtNright,  XawChainLeft,
  1366.                          NULL);
  1367.         }
  1368.         }
  1369.         left = pop->add =
  1370.           XtVaCreateManagedWidget("add", commandWidgetClass, pop->form,
  1371.                       XtNfromVert, up,
  1372.                       XtNtop,    XawChainBottom, 
  1373.                       XtNbottom, XawChainBottom, 
  1374.                       XtNleft,   XawChainLeft, 
  1375.                       XtNright,  XawChainLeft,
  1376.                       NULL);
  1377.         XtAddCallback (pop->add, XtNcallback, add_player_dialog, NULL);
  1378.         left = pop->verify =
  1379.           XtVaCreateManagedWidget("verify", commandWidgetClass, pop->form,
  1380.                       XtNfromVert, up,
  1381.                       XtNfromHoriz, left,
  1382.                       XtNtop,    XawChainBottom, 
  1383.                       XtNbottom, XawChainBottom, 
  1384.                       XtNleft,   XawChainLeft, 
  1385.                       XtNright,  XawChainLeft,
  1386.                       NULL);
  1387.         XtAddCallback (pop->verify, XtNcallback, verify_dialog, NULL);
  1388.         left = pop->ok =
  1389.           XtVaCreateManagedWidget("go", commandWidgetClass, pop->form,
  1390.                       XtNfromVert, up,
  1391.                       XtNfromHoriz, left,
  1392.                       XtNtop,    XawChainBottom, 
  1393.                       XtNbottom, XawChainBottom, 
  1394.                       XtNleft,   XawChainLeft, 
  1395.                       XtNright,  XawChainLeft,
  1396.                       NULL);
  1397.         XtAddCallback (pop->ok, XtNcallback, go_dialog, NULL);
  1398.         pop->cancel =
  1399.           XtVaCreateManagedWidget("quit", commandWidgetClass, pop->form,
  1400.                       XtNfromVert, up,
  1401.                       XtNfromHoriz, left,
  1402.                       XtNtop,    XawChainBottom, 
  1403.                       XtNbottom, XawChainBottom, 
  1404.                       XtNleft,   XawChainLeft, 
  1405.                       XtNright,  XawChainLeft,
  1406.                       NULL);
  1407.         XtAddCallback (pop->cancel, XtNcallback, quit_dialog, NULL);
  1408.     } else {
  1409.         left = pop->ok =
  1410.           XtVaCreateManagedWidget("ok", commandWidgetClass, pop->form,
  1411.                       XtNfromVert, up,
  1412.                       XtNtop,    XawChainBottom, 
  1413.                       XtNbottom, XawChainBottom, 
  1414.                       XtNleft,   XawChainLeft, 
  1415.                       XtNright,  XawChainLeft,
  1416.                       NULL);
  1417.         XtAddCallback (pop->ok, XtNcallback, ok_dialog, NULL);
  1418.         pop->cancel =
  1419.           XtVaCreateManagedWidget("cancel", commandWidgetClass, pop->form,
  1420.                       XtNfromVert, up,
  1421.                       XtNfromHoriz, left,
  1422.                       XtNtop,    XawChainBottom, 
  1423.                       XtNbottom, XawChainBottom, 
  1424.                       XtNleft,   XawChainLeft, 
  1425.                       XtNright,  XawChainLeft,
  1426.                       NULL);
  1427.         XtAddCallback (pop->cancel, XtNcallback, cancel_dialog, NULL);
  1428.     }
  1429.     }
  1430.     XtPopup (pop->shell, XtGrabNone);
  1431.     XMapRaised(XtDisplay(pop->shell), XtWindow(pop->shell));
  1432. }
  1433.  
  1434. static Widget
  1435. createTextWidget(name, parent, up, obj)
  1436. char *name;
  1437. Widget parent, up;
  1438. Obj *obj;
  1439. {
  1440.     Widget w, form;
  1441.  
  1442.     if (obj == lispnil)
  1443.       return NULL;
  1444.  
  1445.     form =
  1446.       XtVaCreateManagedWidget("form", formWidgetClass, parent,
  1447.                   NULL);
  1448.  
  1449.     sprintf(buf1, "%s_label", name);
  1450.     w =
  1451.       XtVaCreateManagedWidget(buf1, labelWidgetClass, form,
  1452.                   XtNlabel, name,
  1453.                   XtNtop,    XawChainTop, 
  1454.                   XtNbottom, XawChainTop, 
  1455.                   XtNleft,   XawChainLeft, 
  1456.                   XtNright,  XawChainLeft,
  1457.                   NULL);
  1458.     w =
  1459.       XtVaCreateManagedWidget(name, asciiTextWidgetClass, form,
  1460.                   XtNfromVert, w,
  1461.                   XtNvertDistance, -1,
  1462.                   XtNdisplayCaret, False,
  1463.                   XtNtop,    XawChainTop, 
  1464.                   XtNbottom, XawChainBottom, 
  1465.                   XtNleft,   XawChainLeft, 
  1466.                   XtNright,  XawChainRight,
  1467.                   NULL);
  1468.     splat_obj_in_textw(w, obj);
  1469.     return w;
  1470. }
  1471.  
  1472. static void
  1473. splat_obj_in_textw(w, obj)
  1474. Widget w;
  1475. Obj *obj;
  1476. {
  1477.     Obj *rest;
  1478.  
  1479.     if (!obj || obj == lispnil)
  1480.       return;
  1481.  
  1482.     if (stringp(obj)) {
  1483.     textw_printf(w, "%s\n", c_string(obj));
  1484.     return;
  1485.     }
  1486.  
  1487.     if (!consp(obj))
  1488.       return;
  1489.  
  1490.     for (rest = obj; rest != lispnil; rest = cdr(rest)) {
  1491.     if (stringp(car(rest))) {
  1492.         textw_printf(w, "%s\n", c_string(car(rest)));
  1493.     }
  1494.     }
  1495. }
  1496.  
  1497. static void
  1498. quit_dialog (w, client_data, call_data)
  1499. Widget w;
  1500. XtPointer client_data;
  1501. XtPointer call_data;
  1502. {
  1503.     exit(0);
  1504. }
  1505.  
  1506.  
  1507. static void
  1508. game_callback (w, client_data, call_data)
  1509. Widget w;
  1510. XtPointer client_data;
  1511. XtPointer call_data;
  1512. {
  1513.     int i;
  1514.  
  1515.     for (i = 0; i < numgames; ++i) {
  1516.     if (w == games[i].name) {
  1517.         popup_game(i, 0);
  1518.         return;
  1519.     }
  1520.     }
  1521. }
  1522.  
  1523. static void
  1524. cancel_dialog (w, client_data, call_data)
  1525. Widget w;
  1526. XtPointer client_data;
  1527. XtPointer call_data;
  1528. {
  1529.     int i;
  1530.     Widget form = XtParent(w);
  1531.  
  1532.     for (i = 0; i < numgames; ++i) {
  1533.     if (games[i].pop && form == games[i].pop->form) {
  1534.         XtPopdown(games[i].pop->shell);
  1535.     }
  1536.     }
  1537. }
  1538.  
  1539. static void
  1540. ok_dialog (w, client_data, call_data)
  1541. Widget w;
  1542. XtPointer client_data;
  1543. XtPointer call_data;
  1544. {
  1545.     int i;
  1546.     Widget form = XtParent(w);
  1547.  
  1548.     for (i = 0; i < numgames; ++i) {
  1549.     if (games[i].pop && form == games[i].pop->form) {
  1550.         break;
  1551.     }
  1552.     }
  1553.     chosen_game = i;
  1554.   
  1555.     /* clean up */
  1556.     for (i = 0; i < numgames; ++i) {
  1557.     if (games[i].pop) {
  1558.         XtPopdown(games[i].pop->shell);
  1559.         XtDestroyWidget(games[i].pop->shell);
  1560.         if (i != chosen_game) {
  1561.         if (games[i].pop->variants)
  1562.           free(games[i].pop->variants);
  1563.         free(games[i].pop);
  1564.         games[i].pop = NULL;
  1565.         }
  1566.     }
  1567.     }
  1568.     XtPopdown(gameShell);
  1569.     XtDestroyWidget(gameShell);
  1570.  
  1571.     /* initialize game and sides */
  1572.     mainmodule = possible_games[chosen_game];
  1573.     load_game_module(mainmodule, TRUE);
  1574.     check_game_validity();
  1575.     make_trial_assignments();
  1576.  
  1577.     popup_game(chosen_game, 1);
  1578. }
  1579.  
  1580. static void
  1581. go_dialog (w, client_data, call_data)
  1582. Widget w;
  1583. XtPointer client_data;
  1584. XtPointer call_data;
  1585. {
  1586.     GamePop *pop = games[chosen_game].pop;
  1587.     char *value;
  1588.     int i, flag;
  1589.  
  1590.     if (!valid_gamepop()) {
  1591.     verify_dialog(w, NULL, NULL);
  1592.     XBell(XtDisplay(pop->shell),50);
  1593.     return;
  1594.     }
  1595.  
  1596.     variants = lispnil;
  1597.     /* setup variants */
  1598.     for (i = 0; i < pop->numvariants; ++i) {
  1599.     value = XawDialogGetValueString(pop->variants[i].dialog);
  1600.     implement_variant(value, &(mainmodule->variants[i]));
  1601.     if (pop->variants[i].mess)
  1602.       free(pop->variants[i].mess);
  1603.     }
  1604.     /* get side values */
  1605.     for (i = 0; i < numsides; ++i) {
  1606.     if (pop->assign[i].pname) {
  1607.         value = XawDialogGetValueString(pop->assign[i].pname);
  1608.         if (value && value[0]) {
  1609.         assignments[i].player->name = copy_string(value);
  1610.         } else {
  1611.         assignments[i].player->name = NULL;
  1612.         }
  1613.         if (pop->assign[i].messname)
  1614.           free(pop->assign[i].messname);
  1615.     }
  1616.     if (pop->assign[i].pid) {
  1617.         value = XawDialogGetValueString(pop->assign[i].pid);
  1618.         flag = type_player(value);
  1619.         if (ABS(flag) == 1) {
  1620.         assignments[i].player->displayname = copy_string(value);
  1621.         assignments[i].player->aitypename  = NULL;
  1622.         } else {
  1623.         assignments[i].player->displayname = NULL;
  1624.         assignments[i].player->aitypename  = copy_string(value);
  1625.         }
  1626.         if (pop->assign[i].messid)
  1627.           free(pop->assign[i].messid);
  1628.     }
  1629.     }
  1630.  
  1631.     XtPopdown(pop->shell);
  1632.     XtDestroyWidget(pop->shell);
  1633.     if (pop->variants)
  1634.       free(pop->variants);
  1635.     if (pop->assign)
  1636.       free(pop->assign);
  1637.     free(pop);
  1638.     free(games);
  1639.     games = NULL;
  1640.  
  1641.     do_module_variants(mainmodule, variants);
  1642.     check_game_validity();
  1643.  
  1644.     loop = 0;
  1645. }
  1646.  
  1647. static int
  1648. valid_gamepop()
  1649. {
  1650.     GamePop *pop = games[chosen_game].pop;
  1651.     char *value;
  1652.     int i, res = 1;
  1653.  
  1654.     /* check variants */
  1655.     for (i = 0; i < pop->numvariants; ++i) {
  1656.     value = XawDialogGetValueString(pop->variants[i].dialog);
  1657.     res = res && valid_variant(value, &(mainmodule->variants[i]));
  1658.     }
  1659.     /* check sides */
  1660.     for (i = 0; i < numsides; ++i) {
  1661.     if (pop->assign[i].pid) {
  1662.         value = XawDialogGetValueString(pop->assign[i].pid);
  1663.         res = res && type_player(value)>0;
  1664.     }
  1665.     }
  1666.  
  1667.     return res;
  1668. }
  1669.  
  1670. static void
  1671. verify_dialog(w, client_data, call_data)
  1672. Widget w;
  1673. XtPointer client_data;
  1674. XtPointer call_data;
  1675. {
  1676.     GamePop *pop = games[chosen_game].pop;
  1677.     char *value;
  1678.     int i, flag;
  1679.  
  1680.     /* save variant values */
  1681.     for (i = 0; i < pop->numvariants; ++i) {
  1682.     value = XawDialogGetValueString(pop->variants[i].dialog);
  1683.     pop->variants[i].value = copy_string(value);
  1684.     if (valid_variant(value, &(mainmodule->variants[i]))) {
  1685.         if (pop->variants[i].mess)  free(pop->variants[i].mess);
  1686.         pop->variants[i].mess = NULL;
  1687.     } else {
  1688.         pop->variants[i].mess = copy_string(errormess);
  1689.     }
  1690.     }
  1691.     /* save side values */
  1692.     for (i = 0; i < numsides; ++i) {
  1693.     if (pop->assign[i].pname) {
  1694.         value = XawDialogGetValueString(pop->assign[i].pname);
  1695.         pop->assign[i].vname = copy_string(value);
  1696.         pop->assign[i].messname = 0;  /* names always OK? */
  1697.     }
  1698.     if (pop->assign[i].pid) {
  1699.         value = XawDialogGetValueString(pop->assign[i].pid);
  1700.         pop->assign[i].vid = copy_string(value);
  1701.         flag = type_player(value);
  1702.         if (flag > 0) {
  1703.         if (pop->assign[i].messid)
  1704.           free(pop->assign[i].messid);
  1705.         pop->assign[i].messid = NULL;
  1706.         } else {
  1707.         pop->assign[i].messid = copy_string(errormess);
  1708.         }
  1709.     }
  1710.     pop->assign[i].vflag = ABS(flag);
  1711.     }
  1712.  
  1713.     XtPopdown(pop->shell);
  1714.     XtDestroyWidget(pop->shell);
  1715.  
  1716.     popup_game(chosen_game, 2);
  1717. }
  1718.  
  1719. static char *
  1720. variant_default(var)
  1721. Variant *var;
  1722. {
  1723.     int i1, i2, i3, i4, i5, n;
  1724.     char *p;
  1725.  
  1726.     switch (keyword_code(c_string(var->id))) {
  1727.       case K_WORLD_SEEN:
  1728.       case K_SEE_ALL:
  1729.       case K_SEQUENTIAL:
  1730.     if (var->dflt == lispnil)  return "true";
  1731.     return c_number(eval(var->dflt)) ? " true" : "false";
  1732.       case K_WORLD_SIZE:
  1733.     sprintlisp(buf3, var->dflt);
  1734.     for (p = buf3; *p; ++p) {
  1735.         if (!isdigit(*p))
  1736.           *p = ' ';
  1737.     }
  1738.     n = sscanf(buf3, "%d%d%d%d%d", &i1, &i2, &i3, &i4, &i5);
  1739.     sprintf(buf3, "(%d %d %d)",
  1740.         (n>0) ? i1 : DEFAULTWIDTH,
  1741.         (n>1) ? i2 : DEFAULTHEIGHT,
  1742.         (n>2) ? i3 : DEFAULTCIRCUMFERENCE);
  1743.     if (n == 4) {
  1744.         sprintf(buf3, "(%d %d %d %d)", i1, i2, i3, i4);
  1745.     }
  1746.     if (n == 5) {
  1747.         sprintf(buf3, "(%d %d %d %d %d)", i1, i2, i3, i4, i5);
  1748.     }
  1749.     return buf3;
  1750.       default:
  1751.     sprintlisp(buf3, var->dflt);
  1752.     return buf3;
  1753.     }
  1754. }
  1755.  
  1756. static char *
  1757. variant_name(var)
  1758. Variant *var;
  1759. {
  1760.     switch (keyword_code(c_string(var->id))) {
  1761.       case K_WORLD_SEEN:
  1762.     sprintf(buf2, "%s: make the world be seen already", var->name);
  1763.     return buf2;
  1764.       case K_SEE_ALL:
  1765.     sprintf(buf2, "%s: make everything be always seen", var->name);
  1766.     return buf2;
  1767.       case K_SEQUENTIAL:
  1768.     sprintf(buf2, "%s: move sequentially", var->name);
  1769.     return buf2;
  1770.       case K_WORLD_SIZE:
  1771.     sprintf(buf2, 
  1772.     "%s: set world size (width height circumference [longitude [latitude]])",
  1773.         var->name);
  1774.     return buf2;
  1775.       default:
  1776.     return var->name;
  1777.     }
  1778. }
  1779.  
  1780. static void
  1781. horizontalDialog(w)
  1782. Widget w;
  1783. {
  1784.     Widget label, value;
  1785.  
  1786.     label = XtNameToWidget(w, "label");
  1787.     value = XtNameToWidget(w, "value");
  1788.     if (label && value) {
  1789.     XtVaSetValues(value,
  1790.               XtNfromVert,  NULL,
  1791.               XtNfromHoriz, label,
  1792.               NULL);
  1793.     }
  1794. }
  1795.  
  1796. static void
  1797. reverseVideoDialog(w)
  1798. Widget w;
  1799. {
  1800.     Pixel fg, bg;
  1801.     Widget label = XtNameToWidget(w, "label");
  1802.  
  1803.     if (!label)
  1804.       return;
  1805.     XtVaGetValues(label, XtNbackground, &bg, XtNforeground, &fg, NULL);
  1806.     XtVaSetValues(w, XtNbackground, fg, NULL);
  1807.     XtVaSetValues(label, XtNbackground, fg, XtNforeground, bg, NULL);
  1808. }
  1809.  
  1810. static int
  1811. boolean_lisp(value)
  1812. char *value;
  1813. {
  1814.     char c, *p;
  1815.  
  1816.     if (!value || !value[0])
  1817.       return 0;
  1818.  
  1819.     for (p = value; *p; ++p) {
  1820.     if (isalnum(*p)){
  1821.         c = tolower(value[0]);
  1822.         return (c != '0' && c != 'n' && c != 'f');
  1823.     }
  1824.     }
  1825.     return FALSE;
  1826. }
  1827.  
  1828. static void
  1829. implement_variant(value, var)
  1830. char *value;
  1831. Variant *var;
  1832. {
  1833.     int key = keyword_code(c_string(var->id)), i1, i2, i3, i4, i5, n;
  1834.     char *p;
  1835.  
  1836.     switch (key) {
  1837.       case K_WORLD_SEEN:
  1838.       case K_SEE_ALL:
  1839.       case K_SEQUENTIAL:
  1840.     push_key_int_binding(&variants, key, boolean_lisp(value));
  1841.     break;
  1842.       case K_WORLD_SIZE:
  1843.     for (p=value; *p; p++) {
  1844.         if (!isdigit(*p))  *p = ' ';
  1845.     }
  1846.     n = sscanf(value, "%d%d%d%d%d", &i1, &i2, &i3, &i4, &i5);
  1847.     if (n < 4)
  1848.       i4 = 0;
  1849.     if (n < 5)
  1850.       i5 = 0;
  1851.     push_key_cdr_binding(&variants, key,
  1852.                  cons(new_number(i1),
  1853.                   cons(new_number(i2),
  1854.                        cons(new_number(i3),
  1855.                         cons(new_number(i4),
  1856.                          cons(new_number(i5),
  1857.                               lispnil))))));
  1858.     break;
  1859.  
  1860.       default:
  1861.     /* what to do here? */
  1862.     break;
  1863.     }
  1864. }
  1865.  
  1866. static int
  1867. valid_variant(value, var)
  1868. char *value;
  1869. Variant *var;
  1870. {
  1871.     int key = keyword_code(c_string(var->id)), i1, i2, i3, i4, i5, n;
  1872.     char *p;
  1873.  
  1874.     errormess[0] = '\0';
  1875.  
  1876.     switch (key) {
  1877.       case K_WORLD_SEEN:
  1878.       case K_SEE_ALL:
  1879.       case K_SEQUENTIAL:
  1880.     return (value && value[0]);
  1881.  
  1882.       case K_WORLD_SIZE:
  1883.     for (p = value; *p; p++) {
  1884.         if (!isdigit(*p))
  1885.           *p = ' ';
  1886.     }
  1887.     n = sscanf(value, "%d%d%d%d%d", &i1, &i2, &i3, &i4, &i5);
  1888.     return (n > 2 && n < 6);
  1889.  
  1890.       default:
  1891.     /* what to do here? */
  1892.     return (value && value[0]);
  1893.     }
  1894. }
  1895.  
  1896. /* return codes:
  1897.    0 = none
  1898.    1 =   valid display
  1899.    2 =   valid machine player
  1900.   -1 = invalid display 
  1901.   -2 = invalid machine player */
  1902.  
  1903. static int
  1904. type_player(value)
  1905. char *value;
  1906. {
  1907.     errormess[0] = '\0';
  1908.     if (!value[0]) {
  1909.     strcpy(errormess, "no player specification");
  1910.     return 0;
  1911.     } else if (strchr(value,':') || !strcmp(value,"here")) {
  1912.     if (can_open_display(value)) {
  1913.         return 1;
  1914.     } else {
  1915.         sprintf(errormess, "cannot open display \"%s\"", value);
  1916.         return -1;
  1917.     }
  1918.     } else {
  1919.     if (strcmp(value,"mplayer")) {
  1920.         sprintf(errormess,
  1921.             "invalid or unkonwn AI \"%s\", try \"mplayer\"", value);
  1922.         return -2;
  1923.     } else {
  1924.         return 2;
  1925.     }
  1926.     }
  1927. }
  1928.  
  1929. static void 
  1930. add_player_dialog(w, client_data, call_data)
  1931. Widget w;
  1932. XtPointer client_data;
  1933. XtPointer call_data;
  1934. {
  1935.     int i, oldnumsides = numsides;
  1936.     GamePop *pop = games[chosen_game].pop;
  1937.  
  1938.     if (numsides >= g_sides_max()) {
  1939.     XBell(XtDisplay(pop->shell),50);
  1940.     return;
  1941.     }
  1942.  
  1943.     add_side_and_player();
  1944.  
  1945.     for (i = oldnumsides; i < numsides; ++i) {
  1946.     init_assignw_player(&(pop->assign[i]), assignments[i].player);
  1947.     pop->assign[i].messid =
  1948.       copy_string("enter display name or \"mplayer\"");
  1949.     }
  1950.  
  1951.     verify_dialog(w, NULL, NULL);
  1952. }
  1953.  
  1954. static void
  1955. init_assignw_player(assignw, player)
  1956. Assignw *assignw;
  1957. Player *player;
  1958. {
  1959.     assignw->vname = (player->name ? player->name : "");
  1960.     if (player->displayname) {
  1961.     assignw->vid = player->displayname;
  1962.     assignw->vflag = 1;
  1963.     } else if (player->aitypename) {
  1964.     assignw->vid = player->aitypename;
  1965.     assignw->vflag = 2;
  1966.     } else {
  1967.     assignw->vid = "";
  1968.     assignw->vflag = 0;
  1969.     }
  1970. }
  1971.  
  1972. static int
  1973. can_open_display(dpyname)
  1974. char *dpyname;
  1975. {
  1976.     Display *dpy;
  1977.  
  1978.     if (dpyname == NULL)
  1979.       return FALSE;
  1980.  
  1981.     if (strcmp("here", dpyname) == 0)
  1982.       dpyname = getenv("DISPLAY");
  1983.  
  1984.     dpy = XOpenDisplay(dpyname);
  1985.     if (dpy) {
  1986.     XCloseDisplay(dpy);
  1987.     return TRUE;
  1988.     } else {
  1989.     return FALSE;
  1990.     }
  1991. }
  1992.  
  1993. /* Shut the side's display down. */
  1994.  
  1995. void
  1996. close_display(side)
  1997. Side *side;
  1998. {
  1999.     Display *dpy = side->ui->dpy;
  2000.  
  2001.     flush_output(side);
  2002.     XSync(dpy, True);
  2003.     /* Mark it as inactive. */
  2004.     side->ui->active = FALSE;
  2005.     /* Clean up after ourselves. */
  2006.     XFreeGC(dpy, side->ui->gc);
  2007.     XFreeGC(dpy, side->ui->textgc);
  2008.     XFreeGC(dpy, side->ui->ltextgc);
  2009.     XFreeGC(dpy, side->ui->terrgc);
  2010.     XFreeGC(dpy, side->ui->unitgc);
  2011.     XFreeGC(dpy, side->ui->emblgc);
  2012.     XtCloseDisplay(dpy);
  2013. }
  2014.